﻿#region File and License Information
/*
<File>
	<License>
		Copyright © 2009 - 2017, Daniel Vaughan. All rights reserved.
		This file is part of Calcium (http://calciumsdk.net), 
		which is released under the MIT License.
		See file /Documentation/License.txt for details.
	</License>
	<CreationDate>2011-02-19 20:50:11Z</CreationDate>
</File>
*/

#endregion

using System;
using System.ComponentModel;
using System.Runtime.CompilerServices;
using System.Windows;
using System.Windows.Media;
using Microsoft.Phone.Controls;
using Microsoft.Phone.Shell;

namespace Outcoder.UI.Xaml
{
	public partial class EnvironmentValues 
	{
		/// <summary>
		/// Determines the <see cref="ThemeType"/> that the application is using.
		/// If the theme is unable to be determined, then the dark theme is assumed.
		/// </summary>
		public ThemeType ThemeType
		{
			get
			{
				if (Application.Current == null)
				{
					return ThemeType.Dark;
				}
				var themeColor = (Color)Application.Current.Resources["PhoneForegroundColor"];
				if (themeColor == null  || themeColor.ToString() == "#FFFFFFFF")
				{
					return ThemeType.Dark;
				}
				return ThemeType.Light;
			}
		}

		DisplayResolution? displayResolution;

		public DisplayResolution DisplayResolution
		{
			get
			{
				if (!displayResolution.HasValue)
				{
					if (Application.Current.Host.Content.ScaleFactor == 100)
					{
						displayResolution = DisplayResolution.Wvga;
					}
					else if (Application.Current.Host.Content.ScaleFactor == 160)
					{
						displayResolution = DisplayResolution.Wxga;
					}
					else if (Application.Current.Host.Content.ScaleFactor == 150)
					{
						displayResolution = DisplayResolution.HD720p;
					}
					else
					{
						throw new InvalidOperationException("Unknown display resolution");
					}
				}

				return displayResolution.Value;
			}
		}

		double? portaitDisplayWidth;

		public double PortaitDisplayWidth
		{
			get
			{
				if (!portaitDisplayWidth.HasValue)
				{
					var resolution = DisplayResolution;
					switch (resolution)
					{
						case DisplayResolution.Wvga:
							portaitDisplayWidth = 480;
							break;
						case DisplayResolution.Wxga:
							portaitDisplayWidth = 768;
							break;
						case DisplayResolution.HD720p:
							portaitDisplayWidth = 720;
							break;
						default:
							throw new InvalidOperationException("Unknown display resolution");
					}
				}

				return portaitDisplayWidth.Value;
			}
		}

		double? portraitDisplayHeight;

		public double PortaitDisplayHeight
		{
			get
			{
				if (!portraitDisplayHeight.HasValue)
				{
					var resolution = DisplayResolution;
					switch (resolution)
					{
						case DisplayResolution.Wvga:
							portraitDisplayHeight = 800;
							break;
						case DisplayResolution.Wxga:
							portraitDisplayHeight = 1280;
							break;
						case DisplayResolution.HD720p:
							portraitDisplayHeight = 1280;
							break;
						default:
							throw new InvalidOperationException("Unknown display resolution");
					}
				}

				return portraitDisplayHeight.Value;
			}
		}

		double? displayWidth;

		public double DisplayWidth
		{
			get
			{
				if (!displayWidth.HasValue)
				{
					var frame = Application.Current.RootVisual as PhoneApplicationFrame;
					if (frame == null)
					{
						throw new Exception("Unable to locate frame to subscribe to orientation change event.");
					}

					frame.OrientationChanged += (sender, args) => SetWidth(frame);

					SetWidth(frame);
				}

				return displayWidth.Value;
			}
		}

		void SetWidth(PhoneApplicationFrame frame)
		{
			displayWidth = frame.Orientation.IsLandscape() ? PortaitDisplayHeight : PortaitDisplayWidth;
		}

		double? displayHeight;

		public double DisplayHeight
		{
			get
			{
				if (!displayHeight.HasValue)
				{
					var frame = Application.Current.RootVisual as PhoneApplicationFrame;
					if (frame == null)
					{
						throw new Exception("Unable to locate frame to subscribe to orientation change event.");
					}

					frame.OrientationChanged += (sender, args) => SetHeight(frame);

					SetHeight(frame);
				}

				return displayHeight.Value;
			}
		}

		void SetHeight(PhoneApplicationFrame frame)
		{
			displayHeight = frame.Orientation.IsPortrait() ? PortaitDisplayHeight : PortaitDisplayHeight;
		}

		void HandleFrameOrientationChanged(object sender, OrientationChangedEventArgs orientationChangedEventArgs)
		{
			OnPropertyChanged("DisplayWidthWhenScaled");
			OnPropertyChanged("DisplayHeightWhenScaled");
		}

		public double DisplayWidthWhenScaled
		{
			get
			{
				return GetScaledSize(true);
			}
		}

		public double DisplayHeightWhenScaled
		{
			get
			{
				return GetScaledSize(false);
			}
		}

		double GetScaledSize(bool getWidth)
		{
			var frame = Application.Current.RootVisual as PhoneApplicationFrame;
			if (frame == null)
			{
				throw new Exception("Unable to retrieve frame.");
			}

			frame.OrientationChanged -= HandleFrameOrientationChanged;
			frame.OrientationChanged += HandleFrameOrientationChanged;

			var page = frame.Content as PhoneApplicationPage;
			if (page != null)
			{
				const double trayWidthInLandscape = 72;
				const double trayHeightInPortrait = 32;

				double barWidthInLandscape = 0;
				double barHeightInPortrait = 0;

				IApplicationBar bar = page.ApplicationBar;

				if (bar != null && bar.Opacity >= 1)
				{
					bool barMinimized = bar.Mode == ApplicationBarMode.Minimized;
					barWidthInLandscape = barMinimized ? 30 : 72;
					barHeightInPortrait = barMinimized ? 30 : 72;
				}

				double trayWidth = 0;
				double trayHeight = 0;

				bool trayVisible = SystemTray.IsVisible;

				if (trayVisible)
				{
					trayWidth = trayWidthInLandscape;
					trayHeight = trayHeightInPortrait;
				}
				
				bool landscape = frame.Orientation.IsLandscape();

				if (landscape)
				{
					return getWidth ? 800 - trayWidth - barWidthInLandscape : 480;
				}
				else
				{
					return getWidth ? 480 : 800 - trayHeight - barHeightInPortrait;
				}
			} 

			return getWidth ? 480 : 800;
		}

		public static string DeviceManufacturer
		{
			get
			{
				return Microsoft.Phone.Info.DeviceStatus.DeviceManufacturer;
			}
		}

		public static string DeviceName
		{
			get
			{
				return Microsoft.Phone.Info.DeviceStatus.DeviceName;
			}
		}
	}

	public enum ThemeType
	{
		Dark,
		Light
	}

	public enum DisplayResolution
	{
		Wvga, 
		Wxga, 
		HD720p
	}
}
